package com.example.picturestorage.controller;

import com.example.picturestorage.bean.TestBean;
import com.example.picturestorage.service.AsyncService;
import com.example.picturestorage.service.TestService;
import com.example.picturestorage.test.AopTest;
import com.example.picturestorage.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.mybatis.logging.Logger;
import org.mybatis.logging.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;

import javax.servlet.http.HttpSession;
import javax.sound.sampled.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;

@Controller
@Slf4j
@SessionAttributes("username")
public class TestController {

    private final static Logger logger = LoggerFactory.getLogger(TestController.class);
    @Autowired
    private AsyncService asyncService;

    @Autowired
    private TestService testService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private StringUtils stringUtils;

    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/asyncTest")
    @ResponseBody
    public String asyncTest() throws InterruptedException {
        asyncService.asyncTest();
        asyncService.asyncTest2();
        return "11";
    }

    @GetMapping("/typeInsertTest")
    @ResponseBody
    public String addTestBean() {
        TestBean testBean = new TestBean()
                .setA(new BigDecimal("11.222"))
                .setB(new Date())
                .setC(LocalDate.now())
                .setD(LocalDateTime.now())
                .setE(LocalTime.now());
        return "" + testService.insertTestBean(testBean);
    }

    @GetMapping("/redisPipelineSet")
    @ResponseBody
    public String redisPipelineSet(){
        Map<String,String> map=new HashMap<>();
        map.put("Tom","11");
        map.put("Frank","12");
        map.put("John","14");
        RedisSerializer<String> stringSerializer = redisTemplate.getStringSerializer();
        List<Object> objects = redisTemplate.executePipelined(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                map.forEach((k, v) -> {
                    connection.set(stringSerializer.serialize(k), stringSerializer.serialize(v));
                });
                return null;
            }
        });
        System.out.println("objects = " + objects);
        return "redisPipeline";
    }

    @GetMapping("/redisPipelineGet")
    @ResponseBody
    public String redisPipelineGet(){
        Map<String,String> map=new HashMap<>();
        map.put("Tom","11");
        map.put("Frank","12");
        map.put("John","14");
        Set<String> strings = map.keySet();
        RedisSerializer<String> stringSerializer = redisTemplate.getStringSerializer();
        List<String> resultList=new ArrayList<>();
        List<Object> objects = redisTemplate.executePipelined(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                strings.forEach(e -> {
                    byte[] key = stringSerializer.serialize(e);
                    byte[] bytes = connection.get(key);
                    String s = new String(bytes);
                    System.out.println("s == " + s);
                    resultList.add(s);

                });
                return null;
            }
        });
        System.out.println("objects = " + objects);
        return resultList.toString();
    }

    @GetMapping("/redisScan")
    @ResponseBody
    public Set<String> redisScan() {
        return redisTemplate.execute((RedisCallback<Set<String>>) connection -> {

            Set<String> binaryKeys = new HashSet<>();

            Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match("a*").count(1000).build());
            while (cursor.hasNext()) {
                binaryKeys.add(new String(cursor.next()));
            }
            System.out.println(cursor.getPosition());
            logger.warn(() -> "ssss");
            return binaryKeys;
        });
    }

    @GetMapping("/redisSetKeys")
    @ResponseBody
    public String redisSetKeys() {
        for (int i = 0; i < 4000; i++) {
            redisTemplate.opsForValue().set(stringUtils.randomString(), stringUtils.randomString());
        }
        return stringUtils.randomString();
    }

    @ModelAttribute("msg")
    public String msg() {
        return serverPort;
    }

    @GetMapping("/testModelAttribute1")
    public String testModelAttribute1() {
        return "test";
    }

    /*@GetMapping("/putModelAttribute")
    public String putModelAttribute(Model model){
        model.addAttribute("str","hello111");
        return "forward:/testModelAttribute2";
    }*/

    @GetMapping("/testModelAttribute2")
    public String testModelAttribute2(@ModelAttribute("msg") String s) {
        log.info("----------------" + s);
        return "test";
    }

    @GetMapping("/testSessionAttributes")
    public String testSessionAttributes(HttpSession session) {
        session.setAttribute("username", "tom");
        return "redirect:/test";
    }

    @GetMapping("/testSessionAttribute")
    public String testSessionAttribute(@SessionAttribute("username") String s, ModelAndView modelAndView) {
        log.info("-------========" + s);
//        modelAndView.setStatus(HttpStatus.NOT_FOUND);
        return "redirect:/test";
    }

    @GetMapping("/modelAndView")
    public ModelAndView returnModelAndView() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("hello");
        modelAndView.setViewName("index");
        return modelAndView;
    }

    @ResponseBody
    @RequestMapping("/test/{name}")
    public String f1(@PathVariable("name") String name) {
        return name;
    }

    @ResponseBody
    @RequestMapping("/test/{name2}")
    public String f2(@PathVariable("name2") String name2) {
        return name2;
    }


    @GetMapping("/closeWindows/{minutes}")
    public String closeWindows(@PathVariable String minutes) throws IOException {
        switch (minutes) {
            case "0":
                Runtime.getRuntime().exec("shutdown -s -t 1");
                break;
            case "5":
                Runtime.getRuntime().exec("shutdown -s -t 300");
                break;
            case "10":
                Runtime.getRuntime().exec("shutdown -s -t 600");
                break;
            default:
                Runtime.getRuntime().exec("shutdown -a");
        }
        return "closeWindows";
    }

    @GetMapping("/closeWindowsHtml")
    public String closeWindows2() {
        return "closeWindows";
    }

    @GetMapping("/openKuGou")
    public String openKuGou() throws IOException {
        Runtime.getRuntime().exec("KuGou");
        return "closeWindows";
    }


    //尝试酷狗播放音乐失败
    @Test
    public void f1() throws IOException, LineUnavailableException, UnsupportedAudioFileException {
//        File file=new File("J:\\KuGou\\王贰浪 - 像鱼.mp3");
        //1 获取你要播放的音乐文件
        File file = new File("J:\\KuGou\\王贰浪 - 像鱼.wav");
        //2、定义一个AudioInputStream用于接收输入的音频数据
        AudioInputStream am;
        //3、使用AudioSystem来获取音频的音频输入流(处理（抛出）异常)
        am = AudioSystem.getAudioInputStream(file);
        //4、使用AudioFormat来获取AudioInputStream的格式
        AudioFormat af = am.getFormat();
        //5、一个源数据行
        SourceDataLine sd;
        //6、获取受数据行支持的音频格式DataLine.info
        //DataLine.Info dl = new DataLine.Info(SourceDataLine.class, af);
        //7、获取与上面类型相匹配的行 写到源数据行里 二选一
        sd = AudioSystem.getSourceDataLine(af);//便捷写法
        //sd = (SourceDataLine) AudioSystem.getLine(dl);
        //8、打开具有指定格式的行，这样可以使行获得资源并进行操作
        sd.open();
        //9、允许某个数据行执行数据i/o
        sd.start();
        //10、写数据
        int sumByteRead = 0; //读取的总字节数
        byte[] b = new byte[320];//设置字节数组大小
        //11、从音频流读取指定的最大数量的数据字节，并将其放入给定的字节数组中。
        while (sumByteRead != -1) {//-1代表没有 不等于-1时就无限读取
            sumByteRead = am.read(b, 0, b.length);//12、读取哪个数组
            if (sumByteRead >= 0) {//13、读取了之后将数据写入混频器,开始播放
                sd.write(b, 0, b.length);

            }
        }
        //关闭
        sd.drain();
        sd.close();
    }

    @Test
    public void f2() throws IOException {
        /*Runtime.getRuntime().exec(new String[]{
               "cmd","cd J:\\KuGou","J:","KuGou 王贰浪 - 像鱼.mp3"
        });*/

//        Runtime.getRuntime().exec(new String[]{
////                "D:\\Program Files (x86)\\KuGou\\KGMusic\\KuGou",
////                "J:\\KuGou\\王贰浪 - 像鱼.mp3 KuGou",
////                "cmd"
////                "cd J:\\KuGou"
//        });
        FileInputStream fileau = new FileInputStream("J:\\KuGou\\王贰浪 - 像鱼.mp3");
        AudioStream as = new AudioStream(fileau);
        AudioPlayer.player.start(as);
    }

    @GetMapping("/test/add")
    @ResponseBody
    public String add() {
        long l1 = System.nanoTime();
        String name = "";
        char i = 0, j = 0, k = 0, l = 0, m = 0, n = 0;
        for (int o = 0; o < 10_000; o++) {
            i = (char) (97 + Math.random() * 26);
            j = (char) (97 + Math.random() * 26);
            k = (char) (97 + Math.random() * 26);
            l = (char) (97 + Math.random() * 26);
            m = (char) (97 + Math.random() * 26);
            n = (char) (97 + Math.random() * 26);
            String s = (i + "").toUpperCase();
            name = "" + s + j + k + l + m + n;
            testService.add(name);
        }
        long l2 = System.nanoTime();
        return "逐条插入时间: " + Duration.ofNanos(l2 - l1).toMillis() + "ms";
    }

    @GetMapping("/test/add2")
    @ResponseBody
    public String add2() {
        long l1 = System.nanoTime();
        String name = "";
        char i = 0, j = 0, k = 0, l = 0, m = 0, n = 0;
        LinkedList<String> strings = new LinkedList<>();
        for (int o = 0; o < 10_000; o++) {
            i = (char) (97 + Math.random() * 26);
            j = (char) (97 + Math.random() * 26);
            k = (char) (97 + Math.random() * 26);
            l = (char) (97 + Math.random() * 26);
            m = (char) (97 + Math.random() * 26);
            n = (char) (97 + Math.random() * 26);
            String s = (i + "").toUpperCase();
            name = "" + s + j + k + l + m + n;
            strings.add(name);
        }
        testService.add2(strings);
        long l2 = System.nanoTime();

        return "批量插入时间: " + Duration.ofNanos(l2 - l1).toMillis() + "ms";
    }

    @Test
    public void fun1() throws InterruptedException {
        long l1 = System.nanoTime();
        Thread.sleep(1000);
        long l2 = System.nanoTime();
        System.out.println(Duration.ofNanos(l2 - l1).toMillis() + "ms");
    }

    @GetMapping("testRedirect")
    public ModelAndView testRedirect(ModelAndView modelAndView) {
        ModelAndView modelAndView1 = new ModelAndView();
        modelAndView1.setViewName("redirect:index");
        return modelAndView1;
    }


    @Autowired
    private AopTest aopTest;

    @GetMapping("/aopTest")
    public String aopTest() {
        String s = aopTest.fun1();
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return s;
    }

    @GetMapping("/aopTest2")
    public String aopTest2() {
        return aopTest.fun2();
    }
}


